﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Diagnostics;

namespace Axe.Imaging
{
    public class BlendItem
    {
        bool m_MakeTransparent = false;
        bool m_ApplyColorTransform = false;
        Color m_TransparentColor = Color.Empty;
        ColorTransform m_TransformColor = new ColorTransform();
        Bitmap m_SourceBitmap = null;
        Point m_OriginPoint = Point.Empty;

        #region public bool ApplyColorTransform
        public bool ApplyColorTransform
        {
            get { return m_ApplyColorTransform; }
            set { m_ApplyColorTransform = value; }
        } 
        #endregion

        #region public ColorTransform TransformColor
        public ColorTransform TransformColor
        {
            get { return m_TransformColor; }
            set { m_TransformColor = value; }
        } 
        #endregion

        #region public Point OriginPoint
        public Point OriginPoint
        {
            get { return m_OriginPoint; }
            set { m_OriginPoint = value; }
        } 
        #endregion

        #region public Color TransparentColor
        public Color TransparentColor
        {
            get { return m_TransparentColor; }
            set { m_TransparentColor = value; }
        } 
        #endregion

        #region public bool MakeTransparent
        public bool MakeTransparent
        {
            get { return m_MakeTransparent; }
            set { m_MakeTransparent = value; }
        } 
        #endregion

        #region public Bitmap SourceBitmap
        public Bitmap SourceBitmap
        {
            get { return m_SourceBitmap; }
            set { m_SourceBitmap = value; }
        }  
        #endregion

        public BlendItem()
        {
        }

        public BlendItem(byte[] imageData)
        {
            using (MemoryStream ms = new MemoryStream(imageData, false))
            {
                SourceBitmap = (Bitmap)Bitmap.FromStream(ms,false,true);
            }
        }

        public void ApplyTransform()
        {
            for (int y = 0; y < SourceBitmap.Height; y++)
            {
                for (int x = 0; x < SourceBitmap.Width; x++)
                {
                    Color c = SourceBitmap.GetPixel(x, y);
                    if (c != Color.Transparent)
                    {
                        c = TransformColor.ApplyTo(c);
                        SourceBitmap.SetPixel(x, y, c);
                    }
                    else
                        Debug.WriteLine("Skipping transparent pixel");
                }
            }
        }
    }

    public class ImageBlender : IDisposable
    {
        int m_Width;
        int m_Height;
        bool m_ClearBackground = false;
        Color m_BackgroundColor = Color.Black;
        List<BlendItem> bmp = new List<BlendItem>();

        #region public int Width
        public int Width
        {
            get { return m_Width; }
            set { m_Width = value; }
        } 
        #endregion

        #region public int Height
        public int Height
        {
            get { return m_Height; }
            set { m_Height = value; }
        } 
        #endregion

        #region public bool ClearBackground
        public bool ClearBackground
        {
            get { return m_ClearBackground; }
            set { m_ClearBackground = value; }
        } 
        #endregion

        #region public Color BackgroundColor
        public Color BackgroundColor
        {
            get { return m_BackgroundColor; }
            set { m_BackgroundColor = value; }
        } 
        #endregion

        public void Add(BlendItem item)
        {
            bmp.Add(item);    
        }

        public void Add(string imageBitmapFile, int x, int y, bool makeTransparent, Color transColor)
        {
            BlendItem item = new BlendItem();

            item.SourceBitmap = (Bitmap)Bitmap.FromFile(imageBitmapFile);
            item.OriginPoint = new Point(x, y);
            item.MakeTransparent = makeTransparent;
            item.TransparentColor = transColor;

            item.TransformColor.Rb = transColor.R;
            item.TransformColor.Gb = transColor.G;
            item.TransformColor.Bb = transColor.B;

            bmp.Add(item);
        }

        public Bitmap Blend()
        {
            Bitmap blendedBmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
            //blendedBmp.SetResolution(bmp[0].SourceBitmap.HorizontalResolution, 
            //    bmp[0].SourceBitmap.VerticalResolution);
     
            using(Graphics gr = Graphics.FromImage(blendedBmp))
            {
                gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                gr.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;

                foreach (BlendItem item in bmp)
                {
                    if (item.MakeTransparent)
                        item.SourceBitmap.MakeTransparent(item.TransparentColor);

                    if (item.ApplyColorTransform)
                        item.ApplyTransform();

                    Point itemSize = new Point(item.SourceBitmap.Width, item.SourceBitmap.Height);

                    gr.DrawImage(item.SourceBitmap, 
                        item.OriginPoint.X,
                        item.OriginPoint.Y, 
                        itemSize.X,
                        itemSize.Y);
                }
            }

            return blendedBmp;
        }

        #region IDisposable Members

        public void Dispose()
        {
            foreach (BlendItem item in bmp)
            {
                item.SourceBitmap.Dispose();
            }
        }

        #endregion
    }
}
